package org.example.order.util;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import jakarta.annotation.PostConstruct;

import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;

@Component
public class JWTUtils {

    @Value("${JWT.sign: myMail}")
    private String signValue;

    @Value("${JWT.expiration.time: 7}")
    private int expirationTimeValue;

    @Value("${JWT.expiration.unit: }")
    private String expirationUnitValue;

    // 静态字段，用于静态方法访问
    private static String sign;
    private static int expirationTime;
    private static String expirationUnit;

    // 在构造后将注入的值复制到静态字段
    @PostConstruct
    public void init() {
        sign = signValue;
        expirationTime = expirationTimeValue;
        expirationUnit = expirationUnitValue;
    }

    /**
     * 生成token  header.payload.singature
     */
    public static String getToken(Map<String, String> map) {
        Calendar instance = Calendar.getInstance();

        // 根据配置的时间单位和值设置过期时间
        int calendarUnit = getCalendarUnit(expirationUnit);
        instance.add(calendarUnit, expirationTime);

        //创建jwt builder
        JWTCreator.Builder builder = JWT.create();

        // payload
        map.forEach((k, v) -> {
            builder.withClaim(k, v);
        });

        String token = builder.withExpiresAt(instance.getTime())  //指定令牌过期时间
                .sign(Algorithm.HMAC256(sign));  // sign
        return token;
    }

    /**
     * 验证token  合法性
     */
    public static DecodedJWT verify(String token) {
        return JWT.require(Algorithm.HMAC256(sign)).build().verify(token);
    }

    /**
     * 获取token中的数据信息
     * @param token JWT令牌
     * @return 包含所有claim的Map
     */
    public static Map<String, String> getTokenData(String token) {
        DecodedJWT decodedJWT = verify(token);
        Map<String, String> dataMap = new HashMap<>();

        // 获取所有claim
        Map<String, Claim> claims = decodedJWT.getClaims();

        // 将claim转换为字符串并存入map
        claims.forEach((key, claim) -> {
            // 尝试获取字符串值，如果不是字符串类型则toString
            String value = claim.asString();
            if (value != null) {
                dataMap.put(key, value);
            } else {
                // 对于非字符串类型的claim，尝试转为字符串
                if (claim.toString() != null) {
                    dataMap.put(key, claim.toString());
                }
            }
        });

        return dataMap;
    }

    /**
     * 获取token中的指定数据
     * @param token JWT令牌
     * @param key 数据键名
     * @return 数据值，如果不存在则返回null
     */
    public static String getTokenData(String token, String key) {
        DecodedJWT decodedJWT = verify(token);
        Claim claim = decodedJWT.getClaim(key);
        if (claim.isNull()) {
            return null;
        }
        return claim.asString();
    }

    /**
     * 转换时间单位字符串为Calendar常量
     */
    private static int getCalendarUnit(String unit) {
        // 添加null检查防止NullPointerException
        if (unit == null) {
            return Calendar.DATE; // 默认为天
        }

        switch (unit.toUpperCase()) {
            case "SECOND":
                return Calendar.SECOND;
            case "MINUTE":
                return Calendar.MINUTE;
            case "HOUR":
                return Calendar.HOUR;
            case "DATE":
            case "DAY":
                return Calendar.DATE;
            case "MONTH":
                return Calendar.MONTH;
            case "YEAR":
                return Calendar.YEAR;
            default:
                return Calendar.DATE; // 默认为天
        }
    }
}